﻿using System;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
using Euresys.clseremc;


namespace GrablinkSerialCommunication
{
    public partial class Form1 : Form
    {
        // Handle to the serial port
        IntPtr serialRef;

        // Index of the serial port
        UInt32 serialIndex;

        // Number of serial ports
        UInt32 numPorts;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.Enabled = false;
            textBox2.Enabled = false;
            textBox2.Text = "Select a serial port";
            openButton.Enabled = false;
            sendButton.Enabled = false;
            readButton.Enabled = false;
            closeButton.Enabled = false;

            // Add path to clseremc in DLL search path
            using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\cameralink"))
            {
                CL.SetDllDirectory((string)registryKey.GetValue("CLSERIALPATH"));
            }

            // Retrieve the number of serial ports
            CL.GetNumSerialPorts(out numPorts);

            // Retrieve the identifier of each port           
            String portIdentifier = "";
            for (int i = 0; i < numPorts; i++)
            {
                UInt32 bufferSize = 0;
                try
                {
                    // Retrieve the buffer size
                    CL.GetSerialPortIdentifier((UInt32)i, System.IntPtr.Zero, out bufferSize);
                }
                catch (Euresys.clSerialException)
                {
                }
                IntPtr textPort = Marshal.AllocHGlobal((int)bufferSize + 1);
                // Retrieve the port identifier
                CL.GetSerialPortIdentifier((UInt32)i, textPort, out bufferSize);
                portIdentifier = Marshal.PtrToStringAnsi(textPort);
                comboBox1.Items.Add(portIdentifier);
                Marshal.FreeHGlobal(textPort);
            }
        }

        private void openButton_Click(object sender, EventArgs e)
        {
            try
            {
                // Open the serial port
                CL.SerialInit(serialIndex, out serialRef);

                // Update the GUI
                textBox2.Text = "";
                textBox1.Text = "";
                closeButton.Enabled = true;
                openButton.Enabled = false;
                sendButton.Enabled = true;
                readButton.Enabled = true;
                textBox1.Enabled = true;
                comboBox1.Enabled = false;
            }
            catch (Euresys.clSerialException error)
            {
                textBox2.Text = error.ToString();
            }
        }

        private void closeButton_Click(object sender, EventArgs e)
        {
            try
            {
                // Close the serial port
                CL.SerialClose(serialRef);

                // Update the GUI
                textBox2.Text = "";
                textBox1.Text = "";
                textBox1.Enabled = false;
                comboBox1.Enabled = true;
                sendButton.Enabled = false;
                readButton.Enabled = false;
                closeButton.Enabled = false;
                openButton.Enabled = true;
            }
            catch (Euresys.clSerialException error)
            {
                textBox2.Text = error.ToString();
            }
        }

        private void sendButton_Click(object sender, EventArgs e)
        {
            try
            {
                // Write the command to the port
                textBox1.Text += Convert.ToChar(13);
                UInt32 numBytes = (UInt32)textBox1.Text.Length;
                CL.SerialWrite(serialRef, textBox1.Text, out numBytes, 5000);

                // Empty the text boxes
                textBox1.Text = "";
                textBox2.Text = "";
            }
            catch (Euresys.clSerialException error)
            {
                textBox2.Text = error.ToString();
                return;
            }
        }

        private void readButton_Click(object sender, EventArgs e)
        {
            try
            {
                // Retrieve the number of bytes in the read buffer
                UInt32 numBytes;
                CL.GetNumBytesAvail(serialRef, out numBytes);

                if (numBytes == 0)
                    textBox2.Text = "<NO DATA>";
                else
                {
                    // Retrieve the data in the read buffer
                    IntPtr receivedData = Marshal.AllocHGlobal((int)numBytes + 1);
                    CL.SerialRead(serialRef, receivedData, out numBytes, 5000);
                    String data = Marshal.PtrToStringAnsi(receivedData, (int)numBytes-1);
                    Marshal.FreeHGlobal(receivedData);
                    textBox2.Text = data;
                }
            }
            catch (Euresys.clSerialException error)
            {
                textBox2.Text = error.ToString();
            }
        }

        private void comboBoxSelectionChanged(object sender, EventArgs e)
        {
            serialIndex = (UInt32)comboBox1.SelectedIndex;

            // Update the GUI
            openButton.Enabled = true;
        }
    }
}
